package module;

import java.sql.Timestamp;
import java.util.Date;
import wargame.entity.*;
import wargame.dao.*;
import java.util.Random;
import java.util.ArrayList;

/**
 *
 * @author peng xiang
 */
public class ManageEmployee {

    public static String employeeSummary(Player p) {
        String employeeSummary = "";
        employeeSummary += "Total No. of Employee:" + EmployeeDAO.playerTotalEmployee(p);
        employeeSummary += "</br>";

        return employeeSummary;
    }

    // pay after 3 turns after the employee hired!
    public static int payEmployeesSalary(Player p) {
        int totalCost = 0;
        ArrayList<Employee> playerEmployees = EmployeeDAO.retrievePlayerEmployees(p);
        for (int i = 0; i < playerEmployees.size(); i++) {
            Employee employee = playerEmployees.get(i);
            // check if it is time to pay for the salary of the employee
            // check if 3 turns have passed.
            if (GameTurn.current_turn - employee.getTurn_hired() != 0
                    && (GameTurn.current_turn - employee.getTurn_hired()) % GlobalConstant.SALARY_TURN == 0) {

                Transaction t = new Transaction();
                t.setPlayer_id(p.getPlayer_id());
                t.setTurn(GameTurn.current_turn);
                t.setCredit_amount(getEmployeeSalary(playerEmployees.get(i)));
                t.setDebit_amount(0);
                t.setDescription("Credit Employee #" + playerEmployees.get(i).getEmployee_id() + " salary");
                TransactionDAO tdao = new TransactionDAO();
                tdao.insertTransaction(t);

                totalCost += getEmployeeSalary(playerEmployees.get(i));
            }
        }
        return totalCost;
    }

    // pay after 3 turns after the employee hired!
    public static int payEmployeesSalaryNextTurn(Player p) {
        int totalCost = 0;
        ArrayList<Employee> playerEmployees = EmployeeDAO.retrievePlayerEmployees(p);
        for (int i = 0; i < playerEmployees.size(); i++) {
            Employee employee = playerEmployees.get(i);
            // check if it is time to pay for the salary of the employee
            // check if 3 turns have passed.
            if ((GameTurn.current_turn + 1) - employee.getTurn_hired() != 0
                    && ((GameTurn.current_turn + 1) - employee.getTurn_hired()) % GlobalConstant.SALARY_TURN == 0) {
                totalCost += getEmployeeSalary(playerEmployees.get(i));
            }
        }
        return totalCost;
    }

    public static void autoGenEmployee() {
        Employee[] employees = new Employee[12];
        Random randSkill = new Random();
        //each time gen ten random employee. 4 w/ 1 skill, 4 w/ 2 skills, 4w/ 3skills
        try {
            for (int i = 0; i < 4; i++) { //4 with 1 skill
                int level = randSkill.nextInt(4) + 1;
                int skill = randSkill.nextInt(8);

                employees[i] = new Employee();
                switch (skill) {
                    case 0:
                        employees[i].setSkillPoints_c_sharp(level);
                        break;
                    case 1:
                        employees[i].setSkillPoints_dot_net(level);
                        break;
                    case 2:
                        employees[i].setSkillPoints_jsp(level);
                        break;
                    case 3:
                        employees[i].setSkillPoints_mssql(level);
                        break;
                    case 4:
                        employees[i].setSkillPoints_mysql(level);
                        break;
                    case 5:
                        employees[i].setSkillPoints_oracle(level);
                        break;
                    case 6:
                        employees[i].setSkillPoints_php(level);
                        break;
                    case 7:
                        employees[i].setSkillPoints_ruby(level);
                        break;
                }
                employees[i].setSalary(getEmployeeSalary(employees[i]));
            }

            for (int t = 4; t < 8; t++) { //4 with 2 skills
                int level = randSkill.nextInt(4) + 1;
                int skill = randSkill.nextInt(8);

                employees[t] = new Employee();
                switch (skill) {
                    case 0:
                        employees[t].setSkillPoints_c_sharp(level);
                        break;
                    case 1:
                        employees[t].setSkillPoints_dot_net(level);
                        break;
                    case 2:
                        employees[t].setSkillPoints_jsp(level);
                        break;
                    case 3:
                        employees[t].setSkillPoints_mssql(level);
                        break;
                    case 4:
                        employees[t].setSkillPoints_mysql(level);
                        break;
                    case 5:
                        employees[t].setSkillPoints_oracle(level);
                        break;
                    case 6:
                        employees[t].setSkillPoints_php(level);
                        break;
                    case 7:
                        employees[t].setSkillPoints_ruby(level);
                        break;
                }

                int level2 = randSkill.nextInt(4) + 1;
                int skill2 = randSkill.nextInt(8);

                switch (skill2) {
                    case 0:
                        employees[t].setSkillPoints_c_sharp(level2);
                        break;
                    case 1:
                        employees[t].setSkillPoints_dot_net(level2);
                        break;
                    case 2:
                        employees[t].setSkillPoints_jsp(level2);
                        break;
                    case 3:
                        employees[t].setSkillPoints_mssql(level2);
                        break;
                    case 4:
                        employees[t].setSkillPoints_mysql(level2);
                        break;
                    case 5:
                        employees[t].setSkillPoints_oracle(level2);
                        break;
                    case 6:
                        employees[t].setSkillPoints_php(level2);
                        break;
                    case 7:
                        employees[t].setSkillPoints_ruby(level2);
                        break;
                }
                employees[t].setSalary(getEmployeeSalary(employees[t]));
            }

            for (int u = 8; u < 12; u++) { //4 with 3 skills
                int level = randSkill.nextInt(4) + 1;
                int skill = randSkill.nextInt(8);

                employees[u] = new Employee();
                switch (skill) {
                    case 0:
                        employees[u].setSkillPoints_c_sharp(level);
                        break;
                    case 1:
                        employees[u].setSkillPoints_dot_net(level);
                        break;
                    case 2:
                        employees[u].setSkillPoints_jsp(level);
                        break;
                    case 3:
                        employees[u].setSkillPoints_mssql(level);
                        break;
                    case 4:
                        employees[u].setSkillPoints_mysql(level);
                        break;
                    case 5:
                        employees[u].setSkillPoints_oracle(level);
                        break;
                    case 6:
                        employees[u].setSkillPoints_php(level);
                        break;
                    case 7:
                        employees[u].setSkillPoints_ruby(level);
                        break;
                }

                int level2 = randSkill.nextInt(4) + 1;
                int skill2 = randSkill.nextInt(8);

                switch (skill2) {
                    case 0:
                        employees[u].setSkillPoints_c_sharp(level2);
                        break;
                    case 1:
                        employees[u].setSkillPoints_dot_net(level2);
                        break;
                    case 2:
                        employees[u].setSkillPoints_jsp(level2);
                        break;
                    case 3:
                        employees[u].setSkillPoints_mssql(level2);
                        break;
                    case 4:
                        employees[u].setSkillPoints_mysql(level2);
                        break;
                    case 5:
                        employees[u].setSkillPoints_oracle(level2);
                        break;
                    case 6:
                        employees[u].setSkillPoints_php(level2);
                        break;
                    case 7:
                        employees[u].setSkillPoints_ruby(level2);
                        break;
                }

                int level3 = randSkill.nextInt(4) + 1;
                int skill3 = randSkill.nextInt(8);

                switch (skill3) {
                    case 0:
                        employees[u].setSkillPoints_c_sharp(level3);
                        break;
                    case 1:
                        employees[u].setSkillPoints_dot_net(level3);
                        break;
                    case 2:
                        employees[u].setSkillPoints_jsp(level3);
                        break;
                    case 3:
                        employees[u].setSkillPoints_mssql(level3);
                        break;
                    case 4:
                        employees[u].setSkillPoints_mysql(level3);
                        break;
                    case 5:
                        employees[u].setSkillPoints_oracle(level3);
                        break;
                    case 6:
                        employees[u].setSkillPoints_php(level3);
                        break;
                    case 7:
                        employees[u].setSkillPoints_ruby(level3);
                        break;
                }
                employees[u].setSalary(getEmployeeSalary(employees[u]));
            }

            EmployeeDAO.storeTempEmployee(employees);

        } catch (Exception e) {
            System.out.println(e.toString());
        }

    }

    //hire employee
    public static boolean hireEmployee(int employee_id, Player p) {
        boolean isAdded = false;
        Employee e = EmployeeDAO.retrieveATempEmployee(employee_id);

        if (e != null) {

            //deduct balance
            int employFee = e.getSalary();
            int playerBalance = p.getBalance();
            playerBalance = playerBalance - employFee;
            int min = 1;
            int max = 5;
            double tolerance = min + (int) (Math.random() * ((max - min)));

            e.setPlayer_id(p.getPlayer_id());
            e.setHours_remaining(50);
            e.setMorale(10);
            e.setTolerance((int) tolerance);
            e.setTurn_hired(GameTurn.current_turn);
//        e.setSalary(getEmployeeSalary(e)); // set when generating the temp employee already.

            if (playerBalance >= 0) {
                //add into employee's table
                int new_employee_id = EmployeeDAO.insertEmployee(e);

                EmployeeDAO.removeTempEmployee(employee_id);

                //add into game log
                GameLog gl = new GameLog(p.getPlayer_id(), "New employee added for" + p.getPlayer_name(), GameTurn.current_turn);
                gl.setTimestamp(new Timestamp(new Date().getTime()));
                GameLogDAO.insertGameLog(gl);

                PlayerDAO.updatePlayerBalance(p.getPlayer_id(), playerBalance);

                //include transactionDAO debit_amount;
                Transaction t = new Transaction();
                t.setPlayer_id(p.getPlayer_id());
                t.setTurn(GameTurn.current_turn);
                t.setCredit_amount(employFee);
                t.setDebit_amount(0);
                t.setDescription("Credit for hiring Employee #" + new_employee_id);
                TransactionDAO tdao = new TransactionDAO();
                tdao.insertTransaction(t);

                isAdded = true;
            } else {
                isAdded = false;
            }
        } else {
            return false;
        }

        return isAdded;
    }

    //fire employee
    public static void fireEmployee(Employee e, Player p) {
        //pay salary + minus player's balance //is firing cost= employee's salary*2?
        int compensation = getEmployeeSalary(e) * 2;
        int playerBalance = p.getBalance() - compensation;
        PlayerDAO.updatePlayerBalance(p.getPlayer_id(), playerBalance);

        //update DB
        EmployeeDAO.deleteEmployee(e);
        //add into log
        GameLog gl = new GameLog(p.getPlayer_id(), "Employee" + e.getEmployee_id() + " was fired.", GameTurn.current_turn);
        gl.setTimestamp(new Timestamp(new Date().getTime()));
        GameLogDAO.insertGameLog(gl);

        Transaction t = new Transaction();
        t.setPlayer_id(p.getPlayer_id());
        t.setTurn(GameTurn.current_turn);
        t.setCredit_amount(compensation);
        t.setDebit_amount(0);
        t.setDescription("Credit for firing Employee #" + e.getEmployee_id());
        TransactionDAO tdao = new TransactionDAO();
        tdao.insertTransaction(t);
    }

    //train employee
    public static String trainEmployee(Employee e, Player p, String skill) {
        Employee trainingEmployee = e;
        if (trainingEmployee.getHours_remaining() >= 40) {

            int trainingCost = 0;
            if (skill.equals("dotnet")) {
                if (trainingEmployee.getSkillPoints_dot_net() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_dot_net() + 1) * 800;
                    trainingEmployee.setSkillPoints_dot_net(trainingEmployee.getSkillPoints_dot_net() + 1);
                } else {
                    return ".Net skill has reach maximum level 4";
                }
            } else if (skill.equals("csharp")) {
                if (trainingEmployee.getSkillPoints_c_sharp() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_c_sharp() + 1) * 800;
                    trainingEmployee.setSkillPoints_c_sharp(trainingEmployee.getSkillPoints_c_sharp() + 1);
                } else {
                    return ".Net skill has reach maximum level 4";
                }

            } else if (skill.equals("php")) {
                if (trainingEmployee.getSkillPoints_php() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_php() + 1) * 800;
                    trainingEmployee.setSkillPoints_php(trainingEmployee.getSkillPoints_php() + 1);
                } else {
                    return "PHP skill has reach maximum level 4";
                }
            } else if (skill.equals("ruby")) {
                if (trainingEmployee.getSkillPoints_ruby() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_ruby() + 1) * 800;
                    trainingEmployee.setSkillPoints_ruby(trainingEmployee.getSkillPoints_ruby() + 1);
                } else {
                    return "Ruby skill has reach maximum level 4";
                }
            } else if (skill.equals("jsp")) {
                if (trainingEmployee.getSkillPoints_jsp() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_jsp() + 1) * 800;
                    trainingEmployee.setSkillPoints_jsp(trainingEmployee.getSkillPoints_jsp() + 1);
                } else {
                    return "JSP skill has reach maximum level 4";
                }
            } else if (skill.equals("mysql")) {
                if (trainingEmployee.getSkillPoints_mysql() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_mysql() + 1) * 800;
                    trainingEmployee.setSkillPoints_mysql(trainingEmployee.getSkillPoints_mysql() + 1);
                } else {
                    return "MySQL skill has reach maximum level 4";
                }
            } else if (skill.equals("mssql")) {
                if (trainingEmployee.getSkillPoints_mssql() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_mssql() + 1) * 800;
                    trainingEmployee.setSkillPoints_mssql(trainingEmployee.getSkillPoints_mssql() + 1);
                } else {
                    return "MsSQL skill has reach maximum level 4";
                }
            } else if (skill.equals("oracle")) {
                if (trainingEmployee.getSkillPoints_oracle() < 4) {
                    trainingCost = (trainingEmployee.getSkillPoints_oracle() + 1) * 800;
                    trainingEmployee.setSkillPoints_oracle(trainingEmployee.getSkillPoints_oracle() + 1);
                } else {
                    return "Oracle skill has reach maximum level 4";
                }
            }

            int playerBalance = p.getBalance();
            playerBalance -= trainingCost;

            if (playerBalance >= 0) {
                //update log
                GameLog gl = new GameLog(p.getPlayer_id(), "Employee" + trainingEmployee.getEmployee_id() + " is one level up for skill:" + skill, GameTurn.current_turn);
                gl.setTimestamp(new Timestamp(new Date().getTime()));
                GameLogDAO.insertGameLog(gl);
                PlayerDAO.updatePlayerBalance(p.getPlayer_id(), playerBalance);
                //set employee remaining hours to zero
                trainingEmployee.setHours_remaining(0);
                EmployeeDAO.updateEmployee(trainingEmployee); //update employee's skill and hour

                Transaction t = new Transaction();
                t.setPlayer_id(p.getPlayer_id());
                t.setTurn(GameTurn.current_turn);
                t.setCredit_amount(trainingCost);
                t.setDebit_amount(0);
                t.setDescription("Credit for training Employee #" + trainingEmployee.getEmployee_id());
                TransactionDAO tdao = new TransactionDAO();
                tdao.insertTransaction(t);

                return "Training successfull!";
            } else {
                return "Training failed! insufficient balance";//condition for player not enough balance
            }
        } else {
            return "Training failed! need to have at least 40 hours to train"; //condition for less than 50hrs
        }

    }

    //employee leaving//every round will have to check
    public static boolean isEmployeeLeaving(Employee e, Player p) {
        e = EmployeeDAO.retrieveEmployee(e.getEmployee_id());

        boolean isLeaving = false;
        double morale = 0;

        int max = 5;
        double roundMorale = (Math.random() * max);
        double probability = 0;

        if (p.getBalance() < 0) {
            probability += 0.20;
        }

        if (EmployeeDAO.employeeProject(e) > 2) {
            probability += 0.20;
        }

        ArrayList<Integer> employeeHour = EmployeeDAO.retrieveEmployeeHour(e.getEmployee_id(), GameTurn.current_turn);
        int totalHour = 0;
        if (employeeHour.size() > 0) {
            for (int hour : employeeHour) {
                totalHour += hour;
            }

            if (totalHour > 40) {
                probability += 0.20;
            }
        }



        //employee with more than 3 level3 skill will leave
        int highlevel = 0;
        if (e.getSkillPoints_c_sharp() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_dot_net() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_jsp() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_mssql() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_mysql() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_oracle() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_php() >= 3) {
            highlevel += 1;
        }
        if (e.getSkillPoints_ruby() >= 3) {
            highlevel += 1;
        }
        if (highlevel >= 3) {
            probability += 0.20;
        }

        //company bad track record, start only after 6 turns
        if (GameTurn.current_turn > 6) {
            if (p.getTrack_record_points() == 0) {
                probability += 0.20;
            }
        }


        roundMorale = probability * roundMorale;
        morale = e.getMorale() - roundMorale;

        if (morale < e.getTolerance()) {
            isLeaving = true;
        } else {
            isLeaving = false;
            e.setMorale((int) morale);
            EmployeeDAO.updateEmployee(e);
        }

        return isLeaving;
    }

    public static void assignEmployeeToProject(Player py, Project p, Employee e, String skill, int hour, int turn) {
        EmployeeDAO.assignEmployee(e, p, skill, hour, turn);
        GameLog gl = new GameLog(py.getPlayer_id(), "Employee" + e.getEmployee_id() + " was assigned to project." + p.getProject_id(), GameTurn.current_turn);
        gl.setTimestamp(new Timestamp(new Date().getTime()));
        GameLogDAO.insertGameLog(gl);

    }

    public static int getEmployeeSalary(Employee e) {
        int salary = 0;
        if (e.getSkillPoints_c_sharp() != 0) {
            switch (e.getSkillPoints_c_sharp()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_dot_net() != 0) {
            switch (e.getSkillPoints_dot_net()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_jsp() != 0) {
            switch (e.getSkillPoints_jsp()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_mysql() != 0) {
            switch (e.getSkillPoints_mysql()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_mssql() != 0) {
            switch (e.getSkillPoints_mssql()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_oracle() != 0) {
            switch (e.getSkillPoints_oracle()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_php() != 0) {
            switch (e.getSkillPoints_php()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }
        if (e.getSkillPoints_ruby() != 0) {
            switch (e.getSkillPoints_ruby()) {
                case 1:
                    salary += 1000;
                    break;
                case 2:
                    salary += 1900;
                    break;
                case 3:
                    salary += 2800;
                    break;
                case 4:
                    salary += 3700;
                    break;
            }
        }

        return salary;
    }

    public static void increaseMorale(Project project) {
        Player p = ProjectDAO.retrievePlayer(project.getProject_id());
        ArrayList<Employee> playerEmployees = EmployeeDAO.retrievePlayerEmployees(p);
        for (Employee e : playerEmployees) {
            double morale = e.getMorale();
            int totalHour = ProjectDAO.totalHours(project.getProject_id(), e.getEmployee_id());
            morale += (totalHour * 0.01);
            e.setMorale(morale);
            EmployeeDAO.updateEmployee(e);
        }
    }
}
